<template>
  <view class="local-data-container">
    <!-- Tab切换 -->
    <view class="tab-container">
      <view 
        class="tab-item" 
        :class="{ 'tab-active': activeTab === 'data' }"
        @click="switchTab('data')"
      >
        <text class="tab-icon">📊</text>
        <text class="tab-text">数据列表</text>
      </view>
      <view 
        class="tab-item" 
        :class="{ 'tab-active': activeTab === 'users' }"
        @click="switchTab('users')"
      >
        <text class="tab-icon">👥</text>
        <text class="tab-text">用户管理</text>
      </view>
    </view>
    
    <!-- 数据列表Tab -->
    <view v-if="activeTab === 'data'" class="tab-content">
      <!-- 顶部统计卡片 -->
      <view class="stats-header">
        <view class="stats-card">
          <view class="stat-icon">📊</view>
          <view class="stat-content">
            <text class="stat-number">{{ dataStats.totalKeys }}</text>
            <text class="stat-label">存储项</text>
          </view>
        </view>
        <view class="stats-card">
          <view class="stat-icon">💾</view>
          <view class="stat-content">
            <text class="stat-number">{{ dataStats.totalSize }}</text>
            <text class="stat-label">总大小</text>
          </view>
        </view>
      </view>

      <!-- 搜索栏 -->
      <view class="search-bar">
        <view class="search-input-wrapper">
          <text class="search-icon">🔍</text>
          <input 
            class="search-input" 
            v-model="searchKeyword" 
            placeholder="搜索数据项..."
            @input="handleSearch"
          />
          <text v-if="searchKeyword" class="clear-icon" @click="clearSearch">✕</text>
        </view>
      </view>

      <!-- 数据列表 -->
      <scroll-view class="data-list" scroll-y>
        <view 
          v-for="item in filteredDataList" 
          :key="item.key"
          class="data-item-card"
          @click="viewDataDetail(item)"
        >
          <view class="data-item-header">
            <view class="data-key-wrapper">
              <text class="data-key">{{ item.key }}</text>
              <text v-if="item.translation" class="data-translation">{{ item.translation }}</text>
            </view>
            <view class="data-badge" :class="`badge-${item.type.toLowerCase()}`">
              {{ item.type }}
            </view>
          </view>
          <view class="data-item-footer">
            <view class="data-meta">
              <text class="data-size">📦 {{ item.size }}</text>
              <text class="data-time">🕐 {{ item.lastModified }}</text>
            </view>
            <text class="data-arrow">›</text>
          </view>
        </view>

        <!-- 空状态 -->
        <view v-if="filteredDataList.length === 0" class="empty-state">
          <text class="empty-icon">📭</text>
          <text class="empty-text">{{ searchKeyword ? '未找到匹配的数据' : '暂无本地数据' }}</text>
        </view>
      </scroll-view>

      <!-- 底部操作栏 -->
      <view class="action-bar">
        <button class="action-btn refresh-btn" @click="refreshData">
          <text class="btn-icon">🔄</text>
          <text class="btn-text">刷新</text>
        </button>
        <button class="action-btn export-btn" @click="handleExportImport">
          <text class="btn-icon">📤</text>
          <text class="btn-text">导出/导入</text>
        </button>
        <button class="action-btn clear-btn" @click="clearAllData">
          <text class="btn-icon">🗑️</text>
          <text class="btn-text">清空</text>
        </button>
      </view>
    </view>

    <!-- 数据详情弹窗 -->
    <view v-if="showDataModal" class="modal-overlay" @click="closeDataModal">
      <view class="modal-content" @click.stop>
        <view class="modal-header">
          <view class="modal-title-wrapper">
            <text class="modal-title">{{ selectedData.key }}</text>
            <text v-if="selectedData.translation" class="modal-subtitle">{{ selectedData.translation }}</text>
          </view>
          <text class="modal-close" @click="closeDataModal">✕</text>
        </view>
        <view class="modal-body">
          <view class="detail-section">
            <text class="section-title">基本信息</text>
            <view class="detail-row">
              <text class="detail-label">数据类型</text>
              <view class="detail-badge" :class="`badge-${selectedData.type?.toLowerCase()}`">
                {{ selectedData.type }}
              </view>
            </view>
            <view class="detail-row">
              <text class="detail-label">数据大小</text>
              <text class="detail-value">{{ selectedData.size }}</text>
            </view>
            <view class="detail-row">
              <text class="detail-label">最后修改</text>
              <text class="detail-value">{{ selectedData.lastModified }}</text>
            </view>
          </view>
          
          <!-- 管理功能区（仅对可管理的数据显示） -->
          <view v-if="isManageableData" class="manage-section">
            <text class="section-title">管理功能</text>
            <view class="manage-buttons">
              <button v-if="isUsersData" class="manage-btn manage-btn-primary" @click="showUserManagement">
                <text class="btn-icon">👥</text>
                <text>切换到用户管理</text>
              </button>
              <button v-if="isGoldData" class="manage-btn manage-btn-warning" @click="showGoldManagement">
                <text class="btn-icon">💰</text>
                <text>金币管理</text>
              </button>
              <button v-if="isEditableData" class="manage-btn manage-btn-info" @click="editData">
                <text class="btn-icon">✏️</text>
                <text>编辑数据</text>
              </button>
            </view>
          </view>
          
          <view class="detail-section">
            <text class="section-title">数据内容</text>
            <!-- 加载状态 -->
            <view v-if="isLoadingContent" class="loading-wrapper">
              <text class="loading-text">加载中...</text>
            </view>
            <!-- JSON数据格式化展示 -->
            <view v-else-if="selectedData.type === 'JSON' || selectedData.type === 'Object'" class="json-content-wrapper">
              <view v-if="parsedContent && Object.keys(parsedContent).length > 0">
                <view 
                  v-for="(value, key) in parsedContent" 
                  :key="key"
                  class="json-item"
                >
                  <view class="json-key-row" :class="{ 'clickable': isExpandable(value) }" @click="isExpandable(value) && toggleExpand(key)">
                    <view class="json-key-left">
                      <text v-if="isExpandable(value)" class="expand-icon">{{ expandedKeys[key] ? '▼' : '▶' }}</text>
                      <text class="json-key">{{ getKeyLabel(key) }}</text>
                      <text class="json-key-cn" v-if="getKeyLabelCn(key)">{{ getKeyLabelCn(key) }}</text>
                    </view>
                    <text v-if="isExpandable(value) && !expandedKeys[key]" class="json-value-preview" :class="getValueClass(value)">
                      {{ formatValuePreview(value) }}
                    </text>
                  </view>
                  <!-- 简单值：始终显示 -->
                  <view v-if="!isExpandable(value)" class="json-value-row">
                    <view class="json-value-simple">
                      <text class="json-value" :class="getValueClass(value)">{{ formatValue(value) }}</text>
                    </view>
                  </view>
                  <!-- 复杂值：展开时显示 -->
                  <view v-if="isExpandable(value) && expandedKeys[key]" class="json-value-row">
                    <view class="json-value-expanded">
                      <text class="json-value" :class="getValueClass(value)">{{ formatValueExpanded(value) }}</text>
                    </view>
                  </view>
                </view>
              </view>
              <view v-else class="empty-content">
                <view class="fallback-content">
                  <text class="content-text" selectable>{{ selectedData.content }}</text>
                </view>
              </view>
            </view>
            <!-- 普通文本内容 -->
            <view v-else class="content-wrapper">
              <text class="content-text" selectable>{{ selectedData.content }}</text>
            </view>
          </view>
        </view>
        
        <view class="modal-footer">
          <button class="modal-btn copy-btn" @click="copyData">
            <text class="btn-icon">📋</text>
            <text>复制</text>
          </button>
          <button v-if="!isManageableData" class="modal-btn delete-btn" @click="deleteData">
            <text class="btn-icon">🗑️</text>
            <text>删除</text>
          </button>
        </view>
      </view>
    </view>
    
    <!-- 用户管理弹窗 -->
    <view v-if="showUserManageModal" class="modal-overlay" @click="closeUserManageModal">
      <view class="modal-content user-manage-modal" @click.stop>
        <view class="modal-header">
          <view class="modal-title-wrapper">
            <text class="modal-title">用户管理</text>
            <text class="modal-subtitle">共 {{ usersList.length }} 个用户</text>
          </view>
          <text class="modal-close" @click="closeUserManageModal">✕</text>
        </view>
        <scroll-view class="user-list" scroll-y>
          <view 
            v-for="(user, index) in usersList" 
            :key="index"
            class="user-item-card"
          >
            <view class="user-item-header">
              <view class="user-info">
                <text class="user-name">{{ user.name || user.email || '未命名用户' }}</text>
                <text class="user-email">{{ user.email || '无邮箱' }}</text>
              </view>
              <view class="user-badges">
                <text v-if="user.role === 'admin'" class="user-badge admin-badge">管理员</text>
                <text v-if="user.pointsData" class="user-badge points-badge">积分: {{ user.pointsData.points || 0 }}</text>
              </view>
            </view>
            <view class="user-item-actions">
              <button class="action-btn-small edit-btn" @click="editUserData(user, index)">
                <text class="btn-icon-small">✏️</text>
                <text>编辑</text>
              </button>
              <button class="action-btn-small delete-btn-small" @click="deleteSingleUser(user, index)">
                <text class="btn-icon-small">🗑️</text>
                <text>删除</text>
              </button>
            </view>
          </view>
          <view v-if="usersList.length === 0" class="empty-state">
            <text class="empty-text">暂无用户数据</text>
          </view>
        </scroll-view>
      </view>
    </view>
    
    <!-- 金币管理弹窗 -->
    <view v-if="showGoldManageModal" class="modal-overlay" @click="closeGoldManageModal">
      <view class="modal-content gold-manage-modal" @click.stop>
        <view class="modal-header">
          <view class="modal-title-wrapper">
            <text class="modal-title">金币管理</text>
          </view>
          <text class="modal-close" @click="closeGoldManageModal">✕</text>
        </view>
        <view class="gold-manage-content">
          <view class="gold-info-card">
            <text class="gold-label">当前金币</text>
            <text class="gold-value">{{ goldData.gold || 0 }}</text>
          </view>
          <view class="gold-actions">
            <button class="gold-action-btn add-btn" @click="modifyGold('add')">
              <text>➕ 增加</text>
            </button>
            <button class="gold-action-btn reduce-btn" @click="modifyGold('reduce')">
              <text>➖ 减少</text>
            </button>
            <button class="gold-action-btn set-btn" @click="modifyGold('set')">
              <text>✏️ 设置</text>
            </button>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 编辑数据弹窗 -->
    <view v-if="showEditModal" class="modal-overlay" @click="closeEditModal">
      <view class="modal-content edit-modal" @click.stop>
        <view class="modal-header">
          <view class="modal-title-wrapper">
            <text class="modal-title">编辑数据</text>
            <text class="modal-subtitle">{{ editFieldLabel }}</text>
          </view>
          <text class="modal-close" @click="closeEditModal">✕</text>
        </view>
        <view class="edit-content">
          <textarea 
            v-model="editValue" 
            class="edit-textarea"
            placeholder="请输入新值..."
            :maxlength="editMaxLength"
          />
          <view class="edit-tips">
            <text class="tip-text">💡 提示：修改后数据将立即生效</text>
          </view>
        </view>
        <view class="modal-footer">
          <button class="modal-btn cancel-btn" @click="closeEditModal">取消</button>
          <button class="modal-btn confirm-btn" @click="saveEditData">保存</button>
        </view>
      </view>
    </view>
    
    <!-- 用户管理Tab -->
    <view v-if="activeTab === 'users'" class="tab-content">
      <scroll-view class="user-list-container" scroll-y>
        <view 
          v-for="(user, index) in usersList" 
          :key="index"
          class="user-item-card"
        >
          <view class="user-item-header">
            <view class="user-info">
              <text class="user-name">{{ user.name || user.email || '未命名用户' }}</text>
              <text class="user-email">{{ user.email || '无邮箱' }}</text>
            </view>
            <view class="user-badges">
              <text v-if="user.role === 'admin'" class="user-badge admin-badge">管理员</text>
              <text v-if="user.pointsData" class="user-badge points-badge">积分: {{ user.pointsData.points || 0 }}</text>
            </view>
          </view>
          <view class="user-item-actions">
            <button class="action-btn-small edit-btn" @click="editUserData(user, index)">
              <text class="btn-icon-small">✏️</text>
              <text>编辑</text>
            </button>
            <button class="action-btn-small delete-btn-small" @click="deleteSingleUser(user, index)">
              <text class="btn-icon-small">🗑️</text>
              <text>删除</text>
            </button>
          </view>
        </view>
        <view v-if="usersList.length === 0" class="empty-state">
          <text class="empty-icon">👤</text>
          <text class="empty-text">暂无用户数据</text>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
import toastHelper from '@/utils/toast-helper.js'

export default {
  data() {
    return {
      dataStats: {
        totalKeys: 0,
        totalSize: '0 KB'
      },
      dataList: [],
      filteredDataList: [],
      searchKeyword: '',
      showDataModal: false,
      selectedData: {},
      parsedContent: null,
      isLoadingContent: false,
      expandedKeys: {}, // 记录展开的键
      // Tab切换
      activeTab: 'data', // data, users
      // 管理功能相关
      showUserManageModal: false,
      showGoldManageModal: false,
      showEditModal: false,
      usersList: [],
      goldData: {},
      editField: '',
      editFieldLabel: '',
      editValue: '',
      editMaxLength: 10000,
      editDataType: 'string' // string, number, boolean
    }
  },
  
  computed: {
    // 解析JSON内容
    parsedJsonContent() {
      if (!this.selectedData || !this.selectedData.content) {
        return null
      }
      
      try {
        if (this.selectedData.type === 'JSON' || this.selectedData.type === 'Object') {
          return JSON.parse(this.selectedData.content)
        }
      } catch (e) {
        return null
      }
      return null
    },
    
    // 判断是否是可管理的数据
    isManageableData() {
      const key = this.selectedData.key
      return key === 'users' || key === 'userGoldData' || key === 'currentUser' || 
             key === 'userPointsData' || key.startsWith('userPointsData_')
    },
    
    // 判断是否是用户数据
    isUsersData() {
      return this.selectedData.key === 'users'
    },
    
    // 判断是否是金币数据
    isGoldData() {
      return this.selectedData.key === 'userGoldData'
    },
    
    // 判断是否是可编辑的数据
    isEditableData() {
      return this.selectedData.type === 'JSON' || this.selectedData.type === 'Object' || 
             this.selectedData.type === 'String'
    }
  },
  
  watch: {
    selectedData: {
      handler(newVal) {
        if (newVal && newVal.content) {
          this.isLoadingContent = true
          // 使用 nextTick 和 setTimeout 确保在移动端也能正确渲染
          this.$nextTick(() => {
            setTimeout(() => {
              try {
                if (newVal.type === 'JSON' || newVal.type === 'Object') {
                  const content = newVal.content
                  if (!content || content.trim() === '') {
                    this.parsedContent = null
                    this.isLoadingContent = false
                    return
                  }
                  
                  // 检查是否是纯数字字符串（这种情况应该被识别为String类型）
                  if (/^\d+$/.test(content.trim())) {
                    this.parsedContent = null
                    this.isLoadingContent = false
                    return
                  }
                  
                  const parsed = JSON.parse(content)
                  // 检查是否是有效对象（不是数组，因为数组在移动端渲染可能有问题）
                  if (parsed && typeof parsed === 'object') {
                    if (Array.isArray(parsed)) {
                      // 数组类型，不进行格式化展示，直接显示原始内容
                      this.parsedContent = null
                    } else if (Object.keys(parsed).length > 0) {
                      this.parsedContent = parsed
                    } else {
                      // 空对象，显示原始内容
                      this.parsedContent = null
                    }
                  } else {
                    // 解析后是基本类型，显示原始内容
                    this.parsedContent = null
                  }
                } else {
                  this.parsedContent = null
                }
              } catch (e) {
                console.error('解析JSON失败:', e, '内容:', newVal.content?.substring(0, 100))
                // 解析失败，显示原始内容
                this.parsedContent = null
              } finally {
                this.isLoadingContent = false
              }
            }, 50) // 给移动端一点时间处理
          })
        } else {
          this.parsedContent = null
          this.isLoadingContent = false
        }
      },
      immediate: true
    }
  },
  
  onLoad() {
    this.loadLocalData()
    this.loadUsersList()
  },
  
  onShow() {
    // 每次显示时刷新数据
    this.loadLocalData()
    if (this.activeTab === 'users') {
      this.loadUsersList()
    }
  },
  
  methods: {
    // 加载本地数据
    loadLocalData() {
      try {
        const info = uni.getStorageInfoSync()
        const allKeys = info.keys
        
        // 计算总大小：累加所有数据项的实际大小
        let totalBytes = 0
        allKeys.forEach(key => {
          try {
            const value = uni.getStorageSync(key)
            const size = this.calculateDataSizeBytes(value)
            totalBytes += size
          } catch (error) {
            console.warn(`计算键 ${key} 大小失败:`, error)
          }
        })
        
        const totalSize = this.formatSize(totalBytes)
        
        this.dataStats.totalKeys = allKeys.length
        this.dataStats.totalSize = totalSize
        
        // 加载所有数据项
        this.dataList = []
        allKeys.forEach(key => {
          try {
            const value = uni.getStorageSync(key)
            const size = this.calculateDataSize(value)
            const type = this.getDataType(value)
            const lastModified = this.getLastModifiedTime(key)
            const translation = this.getKeyTranslation(key)
            
            this.dataList.push({
              key: key,
              type: type,
              size: size,
              lastModified: lastModified,
              translation: translation,
              content: this.formatDataContent(value)
            })
          } catch (error) {
            console.error(`读取键 ${key} 失败:`, error)
          }
        })
        
        // 按键名排序
        this.dataList.sort((a, b) => a.key.localeCompare(b.key))
        
        // 初始化过滤列表
        this.filteredDataList = [...this.dataList]
        
      } catch (error) {
        console.error('加载本地数据失败:', error)
        toastHelper.showError('加载数据失败')
      }
    },
    
    // 搜索处理
    handleSearch() {
      if (!this.searchKeyword.trim()) {
        this.filteredDataList = [...this.dataList]
        return
      }
      
      const keyword = this.searchKeyword.toLowerCase()
      this.filteredDataList = this.dataList.filter(item => {
        return item.key.toLowerCase().includes(keyword) ||
               (item.translation && item.translation.toLowerCase().includes(keyword))
      })
    },
    
    // 清除搜索
    clearSearch() {
      this.searchKeyword = ''
      this.filteredDataList = [...this.dataList]
    },
    
    // 刷新数据
    refreshData() {
      this.loadLocalData()
      toastHelper.showSuccess('数据已刷新')
    },
    
    // 计算数据大小（返回格式化字符串）
    calculateDataSize(value) {
      try {
        const bytes = this.calculateDataSizeBytes(value)
        return this.formatSize(bytes)
      } catch (error) {
        return '0 B'
      }
    },
    
    // 计算数据大小（返回字节数）
    calculateDataSizeBytes(value) {
      try {
        // 将值转换为字符串
        let jsonString
        if (typeof value === 'string') {
          jsonString = value
        } else {
          jsonString = JSON.stringify(value)
        }
        
        // 使用更准确的UTF-8编码大小计算
        return this.estimateStringSize(jsonString)
      } catch (error) {
        console.warn('计算数据大小失败:', error)
        return 0
      }
    },
    
    // 估算字符串大小（UTF-8编码，更准确）
    estimateStringSize(str) {
      if (!str) return 0
      let size = 0
      for (let i = 0; i < str.length; i++) {
        const code = str.charCodeAt(i)
        
        // UTF-8编码大小
        if (code < 0x80) {
          // ASCII字符：1字节
          size += 1
        } else if (code < 0x800) {
          // 2字节字符（如拉丁字符）
          size += 2
        } else if (code < 0xD800 || code >= 0xE000) {
          // 3字节字符（如中文、日文、韩文）
          size += 3
        } else {
          // 4字节字符（代理对，如emoji）
          size += 4
          i++ // 跳过下一个字符（代理对的第二部分）
        }
      }
      return size
    },
    
    // 格式化大小
    formatSize(bytes) {
      if (bytes === 0) return '0 B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    },
    
    // 获取数据类型
    getDataType(value) {
      if (typeof value === 'string') {
        // 如果是纯数字字符串，识别为String而不是JSON
        if (/^\d+$/.test(value.trim())) {
          return 'String'
        }
        // 尝试解析JSON
        try {
          const parsed = JSON.parse(value)
          // 如果解析后是基本类型（非对象/数组），应该识别为String
          if (parsed === null || typeof parsed !== 'object') {
            return 'String'
          }
          // 如果是空对象或空数组，也识别为String
          if (Array.isArray(parsed) && parsed.length === 0) {
            return 'String'
          }
          if (!Array.isArray(parsed) && Object.keys(parsed).length === 0) {
            return 'String'
          }
          return 'JSON'
        } catch {
          return 'String'
        }
      }
      return typeof value === 'object' && value !== null ? 'Object' : typeof value
    },
    
    // 获取键名翻译
    getKeyTranslation(key) {
      const translations = {
        'currentUser': '当前用户',
        'userInfo': '用户信息',
        'users': '用户列表（包含积分数据）',
        'user_token': '用户令牌',
        'currentToken': '当前令牌',
        'isServerLogin': '服务器登录状态',
        'userGoldData': '金币数据',
        'userPointsData': '积分数据（旧版）',
        'userPointsData_': '用户积分数据（旧版）',
        'trustCardsData': '信任卡牌数据',
        'desktopPetData': '桌面宠物数据',
        'friends_list': '好友列表',
        'chat_messages': '聊天消息',
        'app_version': '应用版本',
        'update_info': '更新信息',
        'localLogs': '本地日志',
        'pointsData': '积分数据'
      }
      
      // 检查前缀匹配
      for (const [prefix, translation] of Object.entries(translations)) {
        if (key.startsWith(prefix)) {
          return translation
        }
      }
      
      return translations[key] || null
    },
    
    // 获取最后修改时间
    getLastModifiedTime(key) {
      return new Date().toLocaleString('zh-CN', {
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit'
      })
    },
    
    // 格式化数据内容
    formatDataContent(value) {
      try {
        if (typeof value === 'string') {
          // 尝试解析JSON，如果失败则返回原字符串
          try {
            const parsed = JSON.parse(value)
            // 如果是数组，直接返回字符串形式（避免移动端渲染问题）
            if (Array.isArray(parsed) && parsed.length > 100) {
              return JSON.stringify(parsed, null, 2)
            }
            return JSON.stringify(parsed, null, 2)
          } catch {
            return value
          }
        } else if (typeof value === 'object' && value !== null) {
          // 对于大对象，使用字符串形式
          if (Array.isArray(value) && value.length > 100) {
            return JSON.stringify(value, null, 2)
          }
          return JSON.stringify(value, null, 2)
        } else {
          return String(value)
        }
      } catch (error) {
        console.error('格式化数据内容失败:', error)
        return String(value)
      }
    },
    
    // 查看数据详情
    viewDataDetail(item) {
      // 重置状态
      this.parsedContent = null
      this.isLoadingContent = false
      this.expandedKeys = {}
      this.selectedData = item
      this.showDataModal = true
    },
    
    // 切换展开/折叠
    toggleExpand(key) {
      this.$set(this.expandedKeys, key, !this.expandedKeys[key])
    },
    
    // 判断是否可展开（对象或数组）
    isExpandable(value) {
      return (typeof value === 'object' && value !== null) && 
             (Array.isArray(value) || Object.keys(value).length > 0)
    },
    
    // 格式化值预览（折叠状态）
    formatValuePreview(value) {
      if (Array.isArray(value)) {
        return `数组 [${value.length} 项]`
      }
      if (typeof value === 'object' && value !== null) {
        const keys = Object.keys(value)
        return `对象 {${keys.length} 个属性}`
      }
      return this.formatValue(value)
    },
    
    // 格式化展开的值
    formatValueExpanded(value) {
      if (Array.isArray(value)) {
        if (value.length === 0) return '空数组 []'
        // 显示前5项
        const preview = value.slice(0, 5).map((v, i) => {
          if (typeof v === 'object') {
            return `项${i + 1}: {...}`
          }
          const str = String(v)
          return `项${i + 1}: ${str.length > 30 ? str.substring(0, 30) + '...' : str}`
        }).join('\n')
        return value.length > 5 ? `${preview}\n... (共${value.length}项)` : preview
      }
      if (typeof value === 'object' && value !== null) {
        const keys = Object.keys(value)
        if (keys.length === 0) return '空对象 {}'
        // 显示前10个属性
        const preview = keys.slice(0, 10).map(k => {
          const v = value[k]
          const valStr = typeof v === 'object' ? '{...}' : String(v)
          return `${k}: ${valStr.length > 40 ? valStr.substring(0, 40) + '...' : valStr}`
        }).join('\n')
        return keys.length > 10 ? `${preview}\n... (共${keys.length}个属性)` : preview
      }
      return this.formatValue(value)
    },
    
    // 关闭数据详情弹窗
    closeDataModal() {
      this.showDataModal = false
      this.selectedData = {}
    },
    
    // 复制数据
    copyData() {
      uni.setClipboardData({
        data: this.selectedData.content,
        success: () => {
          toastHelper.showSuccess('已复制到剪贴板')
        }
      })
    },
    
    // 删除数据
    deleteData() {
      uni.showModal({
        title: '删除确认',
        content: `确定要删除 "${this.selectedData.key}" 吗？此操作不可恢复！`,
        confirmColor: '#ff4757',
        success: (res) => {
          if (res.confirm) {
            try {
              uni.removeStorageSync(this.selectedData.key)
              toastHelper.showSuccess('删除成功')
              this.closeDataModal()
              this.loadLocalData()
            } catch (error) {
              console.error('删除数据失败:', error)
              toastHelper.showError('删除失败')
            }
          }
        }
      })
    },
    
    // 处理导出/导入
    handleExportImport() {
      uni.showActionSheet({
        itemList: ['导出数据', '导入数据'],
        success: (res) => {
          if (res.tapIndex === 0) {
            this.exportAllData()
          } else if (res.tapIndex === 1) {
            this.importAllData()
          }
        }
      })
    },
    
    // 导出所有数据为文件
    exportAllData() {
      try {
        const info = uni.getStorageInfoSync()
        const exportData = {}
        
        info.keys.forEach(key => {
          exportData[key] = uni.getStorageSync(key)
        })
        
        const exportString = JSON.stringify(exportData, null, 2)
        const fileName = `local-data-${new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5)}.json`
        
        // #ifdef H5
        // H5平台：使用Blob下载
        const blob = new Blob([exportString], { type: 'application/json;charset=utf-8' })
        const url = URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = url
        link.download = fileName
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        URL.revokeObjectURL(url)
        
        toastHelper.showSuccess('导出成功')
        // #endif
        
        // #ifdef APP-PLUS
        // APP平台：保存到文件系统
        const fs = uni.getFileSystemManager()
        const filePath = `${uni.env.USER_DATA_PATH}/${fileName}`
        
        fs.writeFile({
          filePath: filePath,
          data: exportString,
          encoding: 'utf8',
          success: () => {
            uni.showModal({
              title: '导出成功',
              content: `文件已保存到：${filePath}\n\n您可以在文件管理器中找到此文件。`,
              showCancel: false,
              success: () => {
                // 尝试打开文件管理器
                // #ifdef APP-PLUS
                plus.io.resolveLocalFileSystemURL(filePath, (entry) => {
                  entry.getParent((parentEntry) => {
                    plus.io.resolveLocalFileSystemURL(parentEntry.fullPath, () => {
                      // 可以在这里打开文件管理器
                    })
                  })
                })
                // #endif
              }
            })
          },
          fail: (error) => {
            console.error('保存文件失败:', error)
            toastHelper.showError('保存文件失败')
          }
        })
        // #endif
        
        // #ifdef MP
        // 小程序平台：复制到剪贴板（小程序无法直接下载文件）
        uni.setClipboardData({
          data: exportString,
          success: () => {
            uni.showModal({
              title: '导出成功',
              content: '数据已复制到剪贴板，请粘贴到文件中保存。',
              showCancel: false
            })
          }
        })
        // #endif
      } catch (error) {
        console.error('导出数据失败:', error)
        toastHelper.showError('导出失败')
      }
    },
    
    // 导入所有数据
    importAllData() {
      uni.showModal({
        title: '导入数据',
        content: '导入数据将覆盖当前所有本地数据，此操作不可恢复！\n\n确定要继续吗？',
        confirmColor: '#ff4757',
        success: (res) => {
          if (res.confirm) {
            this.doImportData()
          }
        }
      })
    },
    
    // 执行导入数据
    doImportData() {
      // #ifdef H5
      // H5平台：使用input file
      const input = document.createElement('input')
      input.type = 'file'
      input.accept = '.json'
      input.onchange = (e) => {
        const file = e.target.files[0]
        if (!file) return
        
        const reader = new FileReader()
        reader.onload = (event) => {
          try {
            const importData = JSON.parse(event.target.result)
            this.processImportData(importData)
          } catch (error) {
            console.error('解析文件失败:', error)
            toastHelper.showError('文件格式错误，请确保是有效的JSON文件')
          }
        }
        reader.onerror = () => {
          toastHelper.showError('读取文件失败')
        }
        reader.readAsText(file, 'utf8')
      }
      input.click()
      // #endif
      
      // #ifdef APP-PLUS
      // APP平台：尝试使用uni.chooseFile，如果不支持则提示输入路径
      this.tryChooseFile()
      // #endif
      
      // #ifdef MP
      // 小程序平台：提示用户手动输入
      uni.showModal({
        title: '导入数据',
        content: '请将JSON数据粘贴到输入框中',
        editable: true,
        placeholderText: '粘贴JSON数据...',
        success: (res) => {
          if (res.confirm && res.content) {
            try {
              const importData = JSON.parse(res.content)
              this.processImportData(importData)
            } catch (error) {
              console.error('解析数据失败:', error)
              toastHelper.showError('数据格式错误，请确保是有效的JSON')
            }
          }
        }
      })
      // #endif
    },
    
    // 尝试使用uni.chooseFile（APP平台降级方案）
    tryChooseFile() {
      // 检查是否支持uni.chooseFile
      if (typeof uni.chooseFile === 'function') {
        uni.chooseFile({
          count: 1,
          type: 'file',
          extension: ['.json'],
          success: (res) => {
            const filePath = res.tempFilePaths[0]
            this.readAndImportFile(filePath)
          },
          fail: (error) => {
            console.error('选择文件失败:', error)
            toastHelper.showError('选择文件失败，请检查文件路径')
          }
        })
      } else {
        // 如果不支持，提示用户手动输入文件路径
        uni.showModal({
          title: '选择文件',
          content: '请输入JSON文件的完整路径',
          editable: true,
          placeholderText: '/storage/emulated/0/...',
          success: (res) => {
            if (res.confirm && res.content) {
              this.readAndImportFile(res.content.trim())
            }
          }
        })
      }
    },
    
    // 读取并导入文件
    readAndImportFile(filePath) {
      try {
        const fs = uni.getFileSystemManager()
        fs.readFile({
          filePath: filePath,
          encoding: 'utf8',
          success: (res) => {
            try {
              const importData = JSON.parse(res.data)
              this.processImportData(importData)
            } catch (error) {
              console.error('解析文件失败:', error)
              toastHelper.showError('文件格式错误，请确保是有效的JSON文件')
            }
          },
          fail: (error) => {
            console.error('读取文件失败:', error)
            toastHelper.showError('读取文件失败，请检查文件路径和权限')
          }
        })
      } catch (error) {
        console.error('读取文件异常:', error)
        toastHelper.showError('读取文件失败')
      }
    },
    
    // 处理导入的数据
    processImportData(importData) {
      try {
        if (!importData || typeof importData !== 'object') {
          throw new Error('数据格式错误：必须是对象格式')
        }
        
        // 验证数据格式（检查是否包含常见的存储键）
        const keys = Object.keys(importData)
        if (keys.length === 0) {
          throw new Error('数据为空')
        }
        
        // 导入数据
        let successCount = 0
        let failCount = 0
        
        keys.forEach(key => {
          try {
            const value = importData[key]
            // 如果值是字符串，尝试解析为JSON
            if (typeof value === 'string') {
              try {
                const parsed = JSON.parse(value)
                uni.setStorageSync(key, parsed)
              } catch {
                // 如果解析失败，直接存储字符串
                uni.setStorageSync(key, value)
              }
            } else {
              // 直接存储对象
              uni.setStorageSync(key, value)
            }
            successCount++
          } catch (error) {
            console.error(`导入键 ${key} 失败:`, error)
            failCount++
          }
        })
        
        // 刷新数据
        this.loadLocalData()
        
        // 显示结果
        if (failCount === 0) {
          toastHelper.showSuccess(`导入成功！共导入 ${successCount} 项数据`)
        } else {
          uni.showModal({
            title: '导入完成',
            content: `成功导入 ${successCount} 项数据\n失败 ${failCount} 项`,
            showCancel: false
          })
        }
      } catch (error) {
        console.error('处理导入数据失败:', error)
        toastHelper.showError(`导入失败：${error.message || '未知错误'}`)
      }
    },
    
    // 获取键的中文标签
    getKeyLabel(key) {
      return key
    },
    
    // 获取键的中文说明
    getKeyLabelCn(key) {
      const translations = {
        'id': 'ID',
        'email': '邮箱',
        'name': '姓名',
        'username': '用户名',
        'phone': '手机号',
        'avatar': '头像',
        'role': '角色',
        'token': '令牌',
        'created_at': '创建时间',
        'updated_at': '更新时间',
        'gold': '金币',
        'points': '积分',
        'level': '等级',
        'status': '状态',
        'message': '消息',
        'title': '标题',
        'content': '内容',
        'type': '类型',
        'value': '值',
        'data': '数据',
        'config': '配置',
        'settings': '设置',
        'version': '版本',
        'time': '时间',
        'date': '日期',
        'url': '链接',
        'path': '路径',
        'size': '大小',
        'count': '数量',
        'total': '总计',
        'current': '当前',
        'last': '最后',
        'first': '首次',
        'isLogin': '是否登录',
        'isLoggedIn': '已登录',
        'isServerLogin': '服务器登录',
        'userInfo': '用户信息',
        'userData': '用户数据',
        'gameData': '游戏数据',
        'friendData': '好友数据',
        'pointsData': '积分数据',
        'points': '积分',
        'level': '等级',
        'levelProgress': '等级进度',
        'checkInStatus': '签到状态',
        'lastCheckInDate': '最后签到日期',
        'recentActivities': '最近活动',
        'userId': '用户ID',
        'lastUpdate': '最后更新',
        'email': '邮箱',
        'name': '姓名',
        'avatar': '头像',
        'role': '角色',
        'created_at': '创建时间',
        'password': '密码'
      }
      
      // 检查完整匹配
      if (translations[key]) {
        return translations[key]
      }
      
      // 检查部分匹配
      for (const [en, cn] of Object.entries(translations)) {
        if (key.toLowerCase().includes(en.toLowerCase()) || en.toLowerCase().includes(key.toLowerCase())) {
          return cn
        }
      }
      
      return null
    },
    
    // 格式化值显示
    formatValue(value) {
      if (value === null) return 'null'
      if (value === undefined) return 'undefined'
      if (typeof value === 'boolean') return value ? '是' : '否'
      if (Array.isArray(value)) {
        if (value.length === 0) return '空数组 []'
        // 显示数组前3项
        const preview = value.slice(0, 3).map(v => {
          if (typeof v === 'object') return '{...}'
          return String(v).substring(0, 20)
        }).join(', ')
        return value.length > 3 ? `[${preview}...] (共${value.length}项)` : `[${preview}]`
      }
      if (typeof value === 'object' && value !== null) {
        const keys = Object.keys(value)
        if (keys.length === 0) return '空对象 {}'
        return `{${keys.length}个属性}`
      }
      // 字符串显示完整内容，不截断
      return String(value)
    },
    
    // 获取值的样式类
    getValueClass(value) {
      if (typeof value === 'boolean') return 'value-boolean'
      if (typeof value === 'number') return 'value-number'
      if (typeof value === 'string') return 'value-string'
      if (Array.isArray(value)) return 'value-array'
      if (typeof value === 'object') return 'value-object'
      return 'value-default'
    },
    
    // 清空所有数据
    clearAllData() {
      uni.showModal({
        title: '危险操作',
        content: '确定要清空所有本地数据吗？此操作不可恢复！\n\n包括：用户信息、游戏进度、好友数据等',
        confirmColor: '#ff4757',
        success: (res) => {
          if (res.confirm) {
            try {
              uni.clearStorageSync()
              toastHelper.showSuccess('数据已清空')
              this.loadLocalData()
            } catch (error) {
              console.error('清空数据失败:', error)
              toastHelper.showError('清空失败')
            }
          }
        }
      })
    },
    
    // ========== Tab切换 ==========
    
    // 切换Tab
    switchTab(tab) {
      this.activeTab = tab
      if (tab === 'users') {
        this.loadUsersList()
      }
    },
    
    // 加载用户列表
    loadUsersList() {
      try {
        const usersData = uni.getStorageSync('users')
        if (usersData) {
          this.usersList = JSON.parse(usersData)
        } else {
          this.usersList = []
        }
      } catch (error) {
        console.error('加载用户列表失败:', error)
        this.usersList = []
      }
    },
    
    // ========== 管理功能 ==========
    
    // 显示用户管理（保留用于数据详情中的按钮）
    showUserManagement() {
      this.activeTab = 'users'
      this.loadUsersList()
    },
    
    // 关闭用户管理弹窗（保留兼容性）
    closeUserManageModal() {
      this.showUserManageModal = false
    },
    
    // 删除单个用户
    deleteSingleUser(user, index) {
      const userName = user.name || user.email || '该用户'
      uni.showModal({
        title: '删除用户',
        content: `确定要删除用户 "${userName}" 吗？\n\n此操作将同时删除该用户的积分数据。`,
        confirmColor: '#ff4757',
        success: (res) => {
          if (res.confirm) {
            try {
              // 从users数组中删除
              this.usersList.splice(index, 1)
              uni.setStorageSync('users', JSON.stringify(this.usersList))
              
              // 如果删除的是当前登录用户，清除登录状态
              const currentUser = uni.getStorageSync('currentUser')
              if (currentUser) {
                const current = JSON.parse(currentUser)
                if (current.id === user.id || current.email === user.email) {
                  uni.removeStorageSync('user_token')
                  uni.removeStorageSync('currentUser')
                  uni.removeStorageSync('currentToken')
                }
              }
              
              toastHelper.showSuccess('用户已删除')
              this.loadLocalData()
              this.loadUsersList() // 刷新用户列表
            } catch (error) {
              console.error('删除用户失败:', error)
              toastHelper.showError('删除失败')
            }
          }
        }
      })
    },
    
    // 编辑用户数据
    editUserData(user, index) {
      // 显示编辑弹窗
      this.editField = `users[${index}]`
      this.editFieldLabel = `用户: ${user.name || user.email}`
      this.editValue = JSON.stringify(user, null, 2)
      this.editMaxLength = 50000
      this.editDataType = 'object'
      this.showEditModal = true
    },
    
    // 显示金币管理
    showGoldManagement() {
      try {
        const goldData = uni.getStorageSync('userGoldData')
        if (goldData) {
          this.goldData = JSON.parse(goldData)
        } else {
          this.goldData = { gold: 0 }
        }
        this.showGoldManageModal = true
      } catch (error) {
        console.error('加载金币数据失败:', error)
        toastHelper.showError('加载金币数据失败')
      }
    },
    
    // 关闭金币管理弹窗
    closeGoldManageModal() {
      this.showGoldManageModal = false
      this.goldData = {}
    },
    
    // 修改金币
    modifyGold(action) {
      const currentGold = this.goldData.gold || 0
      let title = ''
      let placeholder = ''
      
      if (action === 'add') {
        title = '增加金币'
        placeholder = '请输入要增加的金币数量'
      } else if (action === 'reduce') {
        title = '减少金币'
        placeholder = '请输入要减少的金币数量'
      } else if (action === 'set') {
        title = '设置金币'
        placeholder = '请输入新的金币数量'
      }
      
      uni.showModal({
        title: title,
        content: `当前金币: ${currentGold}`,
        editable: true,
        placeholderText: placeholder,
        success: (res) => {
          if (res.confirm && res.content) {
            const value = parseInt(res.content)
            if (isNaN(value) || value < 0) {
              toastHelper.showError('请输入有效的数字')
              return
            }
            
            try {
              let newGold = currentGold
              if (action === 'add') {
                newGold = currentGold + value
              } else if (action === 'reduce') {
                newGold = Math.max(0, currentGold - value)
              } else if (action === 'set') {
                newGold = value
              }
              
              this.goldData.gold = newGold
              this.goldData.lastUpdateTime = new Date().toISOString()
              uni.setStorageSync('userGoldData', JSON.stringify(this.goldData))
              
              toastHelper.showSuccess(`金币已${action === 'add' ? '增加' : action === 'reduce' ? '减少' : '设置'}为 ${newGold}`)
              this.loadLocalData()
              this.closeGoldManageModal()
            } catch (error) {
              console.error('修改金币失败:', error)
              toastHelper.showError('修改失败')
            }
          }
        }
      })
    },
    
    // 编辑数据
    editData() {
      // 显示编辑弹窗，允许编辑整个数据
      this.editField = this.selectedData.key
      this.editFieldLabel = this.selectedData.translation || this.selectedData.key
      this.editValue = this.selectedData.content
      this.editMaxLength = 100000
      this.editDataType = this.selectedData.type === 'JSON' || this.selectedData.type === 'Object' ? 'object' : 'string'
      this.showEditModal = true
    },
    
    // 关闭编辑弹窗
    closeEditModal() {
      this.showEditModal = false
      this.editField = ''
      this.editFieldLabel = ''
      this.editValue = ''
      this.editMaxLength = 10000
      this.editDataType = 'string'
    },
    
    // 保存编辑的数据
    saveEditData() {
      try {
        if (!this.editValue || !this.editValue.trim()) {
          toastHelper.showError('数据不能为空')
          return
        }
        
        let valueToSave = this.editValue.trim()
        
        // 如果是对象类型，尝试解析JSON
        if (this.editDataType === 'object') {
          try {
            const parsed = JSON.parse(valueToSave)
            // 如果是users数组中的某个用户，需要更新整个users数组
            if (this.editField.startsWith('users[')) {
              const match = this.editField.match(/users\[(\d+)\]/)
              if (match) {
                const index = parseInt(match[1])
                const usersData = uni.getStorageSync('users')
                if (usersData) {
                  const users = JSON.parse(usersData)
                  users[index] = parsed
                  uni.setStorageSync('users', JSON.stringify(users))
                  toastHelper.showSuccess('用户数据已保存')
                  this.closeEditModal()
                  this.closeDataModal()
                  this.loadLocalData()
                  this.loadUsersList() // 刷新用户列表
                  return
                }
              }
            }
            valueToSave = parsed
          } catch (error) {
            toastHelper.showError('JSON格式错误，请检查数据格式')
            return
          }
        }
        
        // 保存数据
        uni.setStorageSync(this.editField, valueToSave)
        
        toastHelper.showSuccess('数据已保存')
        this.closeEditModal()
        this.closeDataModal()
        this.loadLocalData()
        if (this.activeTab === 'users') {
          this.loadUsersList() // 如果当前在用户管理tab，刷新列表
        }
      } catch (error) {
        console.error('保存数据失败:', error)
        toastHelper.showError('保存失败')
      }
    }
  }
}
</script>

<style scoped>
.local-data-container {
  min-height: 100vh;
  background: linear-gradient(180deg, #f5f7fa 0%, #e9ecef 100%);
  padding-bottom: 120rpx;
  display: flex;
  flex-direction: column;
}

/* Tab切换样式 */
.tab-container {
  display: flex;
  background: #ffffff;
  border-bottom: 2rpx solid #e9ecef;
  padding: 0 20rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  position: sticky;
  top: 0;
  z-index: 100;
}

.tab-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24rpx 0;
  position: relative;
  transition: all 0.3s;
  cursor: pointer;
}

.tab-item::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 4rpx;
  background: transparent;
  transition: all 0.3s;
}

.tab-item.tab-active::after {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.tab-icon {
  font-size: 40rpx;
  margin-bottom: 8rpx;
  opacity: 0.6;
  transition: all 0.3s;
}

.tab-item.tab-active .tab-icon {
  opacity: 1;
  transform: scale(1.1);
}

.tab-text {
  font-size: 26rpx;
  color: #636e72;
  font-weight: 500;
  transition: all 0.3s;
}

.tab-item.tab-active .tab-text {
  color: #667eea;
  font-weight: 600;
}

.tab-content {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* 用户列表容器 */
.user-list-container {
  flex: 1;
  padding: 20rpx;
  height: calc(100vh - 200rpx);
}

/* 统计头部 */
.stats-header {
  display: flex;
  gap: 20rpx;
  padding: 30rpx 20rpx;
  background: transparent;
}

.stats-card {
  flex: 1;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 20rpx;
  padding: 30rpx;
  display: flex;
  align-items: center;
  gap: 20rpx;
  box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.25);
}

.stat-icon {
  font-size: 48rpx;
  opacity: 0.9;
}

.stat-content {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.stat-number {
  font-size: 36rpx;
  font-weight: bold;
  color: #ffffff;
  line-height: 1;
}

.stat-label {
  font-size: 24rpx;
  color: rgba(255, 255, 255, 0.9);
}

/* 搜索栏 */
.search-bar {
  padding: 0 20rpx 20rpx;
}

.search-input-wrapper {
  display: flex;
  align-items: center;
  background: #ffffff;
  border-radius: 16rpx;
  padding: 0 24rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}

.search-icon {
  font-size: 32rpx;
  margin-right: 16rpx;
  opacity: 0.5;
}

.search-input {
  flex: 1;
  height: 80rpx;
  font-size: 28rpx;
  color: #2d3436;
}

.clear-icon {
  font-size: 28rpx;
  color: #999;
  padding: 8rpx;
  margin-left: 8rpx;
}

/* 数据列表 */
.data-list {
  height: calc(100vh - 320rpx);
  padding: 0 20rpx;
}

.data-item-card {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 24rpx;
  margin-bottom: 16rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
}

.data-item-card:active {
  transform: scale(0.98);
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12);
}

.data-item-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 16rpx;
}

.data-key-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.data-key {
  font-size: 28rpx;
  font-weight: 600;
  color: #2d3436;
  line-height: 1.4;
}

.data-translation {
  font-size: 22rpx;
  color: #636e72;
  font-style: italic;
}

.data-badge {
  padding: 6rpx 16rpx;
  border-radius: 12rpx;
  font-size: 20rpx;
  font-weight: 500;
  white-space: nowrap;
}

.badge-json {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}

.badge-object {
  background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
  color: #ffffff;
}

.badge-string {
  background: linear-gradient(135deg, #ed8936 0%, #dd6b20 100%);
  color: #ffffff;
}

.badge-number {
  background: linear-gradient(135deg, #4299e1 0%, #3182ce 100%);
  color: #ffffff;
}

.badge-boolean {
  background: linear-gradient(135deg, #9f7aea 0%, #805ad5 100%);
  color: #ffffff;
}

.data-item-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.data-meta {
  display: flex;
  gap: 24rpx;
  flex: 1;
}

.data-size,
.data-time {
  font-size: 22rpx;
  color: #636e72;
}

.data-arrow {
  font-size: 36rpx;
  color: #b2bec3;
  font-weight: 300;
}

/* 空状态 */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 120rpx 40rpx;
}

.empty-icon {
  font-size: 120rpx;
  margin-bottom: 24rpx;
  opacity: 0.5;
}

.empty-text {
  font-size: 28rpx;
  color: #636e72;
}

/* 底部操作栏 */
.action-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  gap: 16rpx;
  padding: 20rpx;
  background: #ffffff;
  box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.08);
  z-index: 100;
}

.action-btn {
  flex: 1;
  height: 80rpx;
  border-radius: 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  font-size: 28rpx;
  font-weight: 600;
  border: none;
  transition: all 0.3s ease;
}

.refresh-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}

.export-btn {
  background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
  color: #ffffff;
}

.clear-btn {
  background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
  color: #ffffff;
}

.action-btn:active {
  transform: scale(0.96);
}

.btn-icon {
  font-size: 32rpx;
}

.btn-text {
  font-size: 28rpx;
}

/* 弹窗样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 40rpx;
  backdrop-filter: blur(8rpx);
}

.modal-content {
  width: 100%;
  max-width: 700rpx;
  max-height: 90vh;
  background: #ffffff;
  border-radius: 24rpx;
  overflow: hidden;
  box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 32rpx;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}

.modal-title-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.modal-title {
  font-size: 32rpx;
  font-weight: bold;
  line-height: 1.4;
}

.modal-subtitle {
  font-size: 24rpx;
  opacity: 0.9;
  font-style: italic;
}

.modal-close {
  font-size: 36rpx;
  padding: 8rpx;
  margin-left: 16rpx;
  opacity: 0.9;
}

.modal-body {
  flex: 1;
  padding: 32rpx;
  min-height: 200rpx;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  max-height: calc(90vh - 200rpx);
}

.detail-section {
  margin-bottom: 32rpx;
}

.detail-section:last-child {
  margin-bottom: 0;
}

.section-title {
  font-size: 28rpx;
  font-weight: bold;
  color: #2d3436;
  margin-bottom: 20rpx;
  display: block;
}

.detail-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16rpx 0;
  border-bottom: 1rpx solid #f0f0f0;
}

.detail-row:last-child {
  border-bottom: none;
}

.detail-label {
  font-size: 26rpx;
  color: #636e72;
  font-weight: 500;
}

.detail-value {
  font-size: 26rpx;
  color: #2d3436;
  font-weight: 600;
}

.content-wrapper {
  background: #f8f9fa;
  border-radius: 12rpx;
  padding: 24rpx;
  border: 1rpx solid #e9ecef;
  max-height: none;
  min-height: 100rpx;
}

.content-text {
  font-size: 24rpx;
  color: #495057;
  line-height: 1.8;
  word-break: break-word;
  white-space: pre-wrap;
  display: block;
}

/* JSON格式化展示样式 */
.json-content-wrapper {
  background: #f8f9fa;
  border-radius: 12rpx;
  padding: 20rpx;
  border: 1rpx solid #e9ecef;
  max-height: none;
  min-height: 100rpx;
}

.json-item {
  margin-bottom: 24rpx;
  padding-bottom: 24rpx;
  border-bottom: 1rpx solid #e9ecef;
  background: #ffffff;
  border-radius: 12rpx;
  padding: 16rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}

.json-item:last-child {
  margin-bottom: 0;
  padding-bottom: 16rpx;
  border-bottom: none;
}

.json-key-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12rpx;
  margin-bottom: 12rpx;
  padding: 12rpx;
  background: rgba(102, 126, 234, 0.05);
  border-radius: 8rpx;
  transition: all 0.2s ease;
}

.json-key-row.clickable {
  cursor: pointer;
}

.json-key-row.clickable:active {
  background: rgba(102, 126, 234, 0.1);
  transform: scale(0.98);
}

.json-key-left {
  display: flex;
  align-items: center;
  gap: 12rpx;
  flex: 1;
}

.expand-icon {
  font-size: 20rpx;
  color: #667eea;
  width: 24rpx;
  text-align: center;
  font-weight: bold;
}

.json-key {
  font-size: 26rpx;
  font-weight: 600;
  color: #667eea;
  background: rgba(102, 126, 234, 0.1);
  padding: 6rpx 16rpx;
  border-radius: 8rpx;
}

.json-key-cn {
  font-size: 22rpx;
  color: #636e72;
  font-style: italic;
  padding: 4rpx 12rpx;
  background: rgba(99, 110, 114, 0.1);
  border-radius: 6rpx;
}

.json-value-row {
  padding-left: 36rpx;
  margin-top: 8rpx;
}

.json-value-simple {
  padding: 12rpx 16rpx;
  background: #ffffff;
  border-radius: 8rpx;
  border: 1rpx solid #e9ecef;
  border-left: 3rpx solid #667eea;
}

.json-value-expanded {
  padding: 16rpx;
  background: #ffffff;
  border-radius: 8rpx;
  border: 1rpx solid #e9ecef;
  border-left: 3rpx solid #48bb78;
}

.json-value {
  font-size: 24rpx;
  line-height: 1.8;
  word-break: break-word;
  display: block;
  white-space: pre-wrap;
}

.json-value-preview {
  font-size: 22rpx;
  padding: 6rpx 12rpx;
  border-radius: 6rpx;
  background: rgba(102, 126, 234, 0.1);
  font-weight: 500;
}

.value-string {
  color: #48bb78;
  font-weight: 500;
}

.value-number {
  color: #4299e1;
  font-weight: 600;
}

.value-boolean {
  color: #9f7aea;
  font-weight: 600;
}

.value-array {
  color: #ed8936;
  font-weight: 500;
}

.value-object {
  color: #667eea;
  font-weight: 500;
}

.value-default {
  color: #495057;
}

/* 加载状态 */
.loading-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60rpx 20rpx;
  background: #f8f9fa;
  border-radius: 12rpx;
  min-height: 200rpx;
}

.loading-text {
  font-size: 28rpx;
  color: #636e72;
}

/* 空内容状态 */
.empty-content {
  background: #f8f9fa;
  border-radius: 12rpx;
  padding: 24rpx;
  border: 1rpx solid #e9ecef;
}

.empty-text {
  font-size: 24rpx;
  color: #999;
  margin-bottom: 16rpx;
  display: block;
}

.fallback-content {
  margin-top: 16rpx;
  padding-top: 16rpx;
  border-top: 1rpx solid #e9ecef;
}

.modal-footer {
  display: flex;
  gap: 16rpx;
  padding: 24rpx 32rpx;
  border-top: 1rpx solid #f0f0f0;
  background: #fafbfc;
}

.modal-btn {
  flex: 1;
  height: 80rpx;
  border-radius: 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  font-size: 28rpx;
  font-weight: 600;
  border: none;
  transition: all 0.3s ease;
}

.copy-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}

.delete-btn {
  background: linear-gradient(135deg, #ff4757 0%, #ff3742 100%);
  color: #ffffff;
}

.modal-btn:active {
  transform: scale(0.96);
}

/* 管理功能区样式 */
.manage-section {
  background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
  border-radius: 16rpx;
  padding: 24rpx;
  margin: 20rpx 0;
  border: 1rpx solid #e9ecef;
}

.manage-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
  margin-top: 16rpx;
}

.manage-btn {
  flex: 1;
  min-width: 200rpx;
  height: 80rpx;
  border-radius: 12rpx;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12rpx;
  font-size: 26rpx;
  font-weight: 600;
  color: #ffffff;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  transition: all 0.3s;
}

.manage-btn:active {
  transform: scale(0.95);
  opacity: 0.8;
}

.manage-btn-primary {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.manage-btn-warning {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}

.manage-btn-info {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}

.manage-btn .btn-icon {
  font-size: 32rpx;
}

/* 用户管理弹窗样式 */
.user-manage-modal {
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.user-list {
  flex: 1;
  padding: 20rpx;
  max-height: calc(80vh - 200rpx);
}

.user-item-card {
  background: #ffffff;
  border-radius: 16rpx;
  padding: 24rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  border: 1rpx solid #e9ecef;
}

.user-item-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 20rpx;
}

.user-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.user-name {
  font-size: 30rpx;
  font-weight: 600;
  color: #2d3436;
}

.user-email {
  font-size: 24rpx;
  color: #636e72;
}

.user-badges {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
  align-items: flex-end;
}

.user-badge {
  font-size: 22rpx;
  padding: 6rpx 12rpx;
  border-radius: 8rpx;
  color: #ffffff;
  font-weight: 500;
}

.admin-badge {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}

.points-badge {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}

.user-item-actions {
  display: flex;
  gap: 16rpx;
}

.action-btn-small {
  flex: 1;
  height: 64rpx;
  border-radius: 10rpx;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8rpx;
  font-size: 24rpx;
  font-weight: 500;
  color: #ffffff;
}

.edit-btn {
  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}

.delete-btn-small {
  background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
}

.action-btn-small .btn-icon-small {
  font-size: 28rpx;
}

/* 金币管理弹窗样式 */
.gold-manage-modal {
  max-width: 600rpx;
}

.gold-manage-content {
  padding: 30rpx;
}

.gold-info-card {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  border-radius: 20rpx;
  padding: 40rpx;
  text-align: center;
  margin-bottom: 30rpx;
  box-shadow: 0 8rpx 24rpx rgba(245, 87, 108, 0.3);
}

.gold-label {
  display: block;
  font-size: 26rpx;
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 16rpx;
}

.gold-value {
  display: block;
  font-size: 64rpx;
  font-weight: bold;
  color: #ffffff;
}

.gold-actions {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.gold-action-btn {
  height: 80rpx;
  border-radius: 12rpx;
  border: none;
  font-size: 28rpx;
  font-weight: 600;
  color: #ffffff;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}

.add-btn {
  background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
}

.reduce-btn {
  background: linear-gradient(135deg, #ee0979 0%, #ff6a00 100%);
}

.set-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

/* 编辑数据弹窗样式 */
.edit-modal {
  max-width: 90%;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.edit-content {
  flex: 1;
  padding: 30rpx;
  display: flex;
  flex-direction: column;
}

.edit-textarea {
  flex: 1;
  min-height: 400rpx;
  background: #f8f9fa;
  border: 1rpx solid #e9ecef;
  border-radius: 12rpx;
  padding: 20rpx;
  font-size: 26rpx;
  color: #2d3436;
  line-height: 1.6;
  font-family: 'Courier New', monospace;
}

.edit-tips {
  margin-top: 16rpx;
  padding: 16rpx;
  background: #fff3cd;
  border-radius: 8rpx;
  border-left: 4rpx solid #ffc107;
}

.tip-text {
  font-size: 24rpx;
  color: #856404;
}

.cancel-btn {
  background: #6c757d;
  color: #ffffff;
}

.confirm-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
}
</style>
